#ifndef RTPTHREAD_H
#define RTPTHREAD_H
#pragma once
#include "jthread.h"
#include "rtpsession.h"
#include "rtpsourcedata.h"
#include "rtpsessionparams.h"
#include "rtpudpv4transmitter.h"
#include "rtpudpv6transmitter.h"
#include "rtpipv4address.h"
#include "rtpipv6address.h"
#include "rtptimeutilities.h"
#include "rtppacket.h"


#include "audio\AudioInGrabber.h"
#include "audio\AudioOutGrabber.h"

#include <speex\speex.h>  
#pragma comment(lib,"libspeex.lib")
#define _SPEEX_DSP
#ifdef _SPEEX_DSP
#include <speex\speex_preprocess.h>
#include <speex\speex_echo.h> 
#pragma comment(lib,"libspeexdsp.lib") 
#endif // _SPEEX
#define FRAME_SIZE 160  

class CRtpVideoThread;
class CRtpAudioThread :private JThread,CAudioInGrabber,CAudioOutGrabber
{
private:
	RTPSession ss;
	RTPSessionParams sp;
	RTPUDPv4TransmissionParams tp4;
	void *Thread();

	uint8_t *m_pstrReciveBuffer;
	uint16_t m_nLocalPort;
	uint32_t m_nTargetIP;
	uint16_t m_nTargetPort;
	bool m_bSetTarget;
	bool m_bThreadDone;
	uint8_t m_nPayloadType;
	bool m_bMute;
	JMutex mutex;
	virtual void GetData(BYTE *pBuffer,long iLen);

	void *stateEncode;  
    void *stateDecode; 

	SpeexBits bitsEncode;  
	SpeexBits bitsDecode; 
#ifdef _SPEEX_DSP
	SpeexPreprocessState * m_Inputst;
	SpeexPreprocessState * m_Outputst;
	SpeexEchoState *echo_state; 
#endif // _SPEEX

	unsigned int nSendDateSize;
	BYTE * pSendBuffer;

	unsigned int  nOutBufLen;
	BYTE * pOutBuffer;
	FILE * m_PCMFile;
	int m_nTimes;
public:
	CRtpAudioThread(void);
	virtual ~CRtpAudioThread(void);
	CRtpVideoThread * m_VideoRtp;
public:
	uint32_t application_data;
	bool GetLocalPort(uint16_t & port);
	bool GetTarget(uint32_t &ip, uint16_t &port);
	bool SetTarget(uint32_t ip, uint16_t port);
	bool SetPayloadType(uint8_t nPayloadType);
	bool SendDTMF(const char * cKey='\0');
	bool muteMic(bool bMute);
	LONG SetEarphoneVolume(LONG nVolume);
	LONG SetMicVolume(LONG nVolume);
	bool PlayPCM(const char * szFullName,INT nTimes);
	bool StopPCM();

};


class H264Decoder ;
class H264Encoder ;
class H263Encoder ;
class H263Decoder ;
class CCameraDS;
#define CAM_WIDTH 640
#define CAM_HEIGHT 480

//#define CAM_WIDTH 176
//#define CAM_HEIGHT 144
class CRtpVideoThread :private JThread
{
private:
	H264Decoder * m_h264decoder;
	H264Encoder * m_h264encoder;
	H263Encoder * m_h263encoder;
	H263Decoder * m_h263decoder;


	RTPSession ss;
	RTPSessionParams sp;
	RTPUDPv4TransmissionParams tp4;

	void *Thread();



	bool m_bThreadDone;

	uint8_t m_nPayloadType;



	static DWORD WINAPI CameraCaptureThread(LPVOID lpParameter);
	HANDLE m_hCameraThread;
	BOOL m_bCameraThreadIsRuning;


	CCameraDS * m_CameraDS;
	int m_nCameraCount;
	bool m_bCameraOpened;

	DWORD m_nRemoteVideoBufferLen;
	BYTE * m_RemoteVideoBuffer;
	DWORD m_nLocaleVideoBufferLen;
	BYTE * m_LocaleVideoBuffer;
	DWORD m_nYUV420BufferLen;
	BYTE * m_YUV420Buffer;
	BYTE * m_YUV420[4];



	uint16_t m_nLocalPort;
	uint32_t m_nTargetIP;
	uint16_t m_nTargetPort;
	bool m_bSetTarget;


	CRtpVideoThread(void){};
public:
	CRtpVideoThread(uint8_t nPayloadType);
	virtual ~CRtpVideoThread(void);
public:
	bool OpenCamera(int nIndex =0);
	bool CloseCamera();
	bool GetLocalPort(uint16_t & port);
	bool GetTarget(uint32_t &ip, uint16_t &port);
	bool SetTarget(uint32_t ip, uint16_t port);


	int GetRGBBufferSize()
	{
		return CAM_WIDTH*CAM_HEIGHT*3;
	};
	int GetVideo(BYTE * pBuffer,BOOL bLocale=true);
	BYTE * GetBuffer(BOOL bLocale=true)
	{
		if(bLocale)
			return m_LocaleVideoBuffer;
		else
			return m_RemoteVideoBuffer;
	};
};
#endif